#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

// 固定队列大小
#define QueueSize 10

// 定义顺序队列结构体
typedef struct queue
{
    char data[QueueSize]; // 队列元素(基于静态char数组，后续大小固定不能改变， 动态数组后续可通过 realloc 重新分配)
    int front;            // 对头
    int rear;             // 队尾
} Queue, *SeqQueue;

// 定义别名，循环队列. 用原始名称 或者 跟在定义的结构体后面，vscode 才可引用属性
typedef struct queue *CircularQueue;


CircularQueue create(unsigned size){
    CircularQueue CQ = (CircularQueue)malloc(sizeof(Queue));
    CQ->front = CQ->rear = 0;
    return CQ;
}

// 置空队列
void initQueue(CircularQueue q)
{
    if (q == NULL)
    {
        printf("error initializing circular queue, can't be null\n");
        exit(0);
    }
    q->front = q->rear = 0;
}

// 判队空
int queueEmpty(CircularQueue q)
{
    return q->rear == q->front;
}
// 判队满
int queueFull(CircularQueue q)
{
    return (q->rear + 1) % QueueSize == q->front;
}
// 入队列
void enQueue(CircularQueue q, char x)
{
    if (queueFull(q))
    {
        printf("the circular queue is full\n");
        return;
    }

    q->data[q->rear] = x;
    q->rear = (q->rear + 1) % QueueSize; // 循环意义下加1
    printf("enqueue value>>%c, front=%d, rear=%d\n", x, q->front, q->rear);
}
// 出队列
char deQueue(CircularQueue q)
{
    if (queueEmpty(q))
    {
        printf("the circular queue is empty, will exit\n");
        // exit(0);
        return CHAR_MIN;
    }

    char x = q->data[q->front];
    q->front = (q->front + 1) % QueueSize; // 头指针+1
    printf("dequeue value>>%c, front=%d, rear=%d\n", x, q->front, q->rear);
    return x;
}
// 取队头
char getFront(CircularQueue q)
{
    if (queueEmpty(q))
    {
        printf("queue is empty, will exit\n");
        // exit(0);
        return CHAR_MIN;
    }

    return q->data[q->front];
}

int main()
{
    CircularQueue cq = (CircularQueue)malloc(sizeof(Queue));
    initQueue(cq);

    printf("-----------circular enqueue----------\n");
    char ch;
    while ((ch = getchar()) != '\n')
    {
        enQueue(cq, ch);
    }

    printf("----------circular dequeue-------------\n");

    do
    {
        deQueue(cq);
    } while (!queueEmpty(cq));

    return 0;
}